
/**************************************************************
	LMtmr_Set_Timer 				1 unit = 625us
	rdabt_timer_create		  		1 unit = 100ms
 ***************************************************************/
 
 
#include "sys_config.h"
#include "sys_types.h"
#include "sys_hal_features.h"
#include "l2cap_primitives.h"
#include "l2_const.h"
#include "l2_types.h"
#include "l2_channel.h"
#include "host_config.h"
#include "papi.h"
#include "sys_rda_arm.h"
#include "hid.h"

#include "hid_core.h"
#include "lmp_link_policy_protocol.h"
#include "tra_queue.h"
#include "tra_combined.h"
#include "lmp_scan.h"
#include "lmp_acl_connection.h"
#include "lmp_ch.h"
#include "hw_i2c_driver.h"
#include "bt_timer.h"
#include "hs_main.h"
#include "hs_battery.h"
#include "hw_delay.h"
#include "sys_power.h"
#include "lmp_utils.h"
#include "lmp_link_key_db.h"
#include "lmp_timer.h"
#include "hw_apb_spi.h"
#include "papi.h"
//#include "manager.h"
#include "bt_test.h"
//#include "mgr_link.h"
#include "sdp_db.h"
#include "spp_dun.h"

#include "uslc_sleep_ctrl_states.h"
#include "rfcomm_frame.h"
#include "rfcomm_proto.h"
 
 
 //#include "hcit_chimera_16550_serial.h"
#include "hid_main.h"
 
#include "hfp.h"
#include "hs_battery.h"
#include "tc_interface.h"
#include "hw_spiflash_driver.h"



#define TEST_FLASH

#define USE_FOR_CONNECT_RF



#define HID_DEBUG_SCAN			0x20
#define HID_DEBUG_KEY_RECONN	0x40


#define DTECT_POWER_INTERVAL  10 // 1s


extern u_int8 HW_Random_Read(u_int8* data);
extern void _HWradio_ProgNow(u_int32 data);

u_int8 gEfuse[8];

u_int8 gPowerT;

extern u_int8 silence_frame[77];  // Notice: use the buffer of 5869's codec

extern struct st_t_SDP_attribute attribute_pnp[];
extern t_dut_mode      BTtst_dut_mode;
extern u_int8   	hFifoIndex;	
extern u_int8   gLinkIndex;
extern u_int8 _r2p_min_search_window;
extern u_int8 g_min_wakeup_interval;
extern t_SYS_Config g_sys_config;
extern u_int8 r71TestFlag;
extern volatile u_int32 *hid_func_db;
extern HID   ghid;
extern t_hid_pskey  hid_config_eeprom;


__align(4) const u_int8  MY_KB_scan_table[18 * 8]=
{
// col 0    r1    r2    r3   r4    r5    r6    r7
	0x04/*a*/, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
// col 1
	0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
// col 2
    0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
// col 3
    0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
//  col 4
	0x24, 0x25, 0x26, 0x27/*0*/, 0x10, 0x22, 0x19, 0x21,
//  col 5
	0x12, 0x1c, 0x0d, 0x0b, 0x11, 0x23, 0x05, 0x24,		
//  col 6
	0x0c, 0x31,	0x0e, 0x0b,	0x10, 0x2e,	0x2e, 0x25,
//  col 7	
	0x18, 0x1c,	0x0f, 0x52,	0x36, 0x05,	0x50, 0x26,
//  col8
	0x13, 0x38,	0x28, 0x30, 0x33, 0x37,	0x2d, 0x27,
//  col9
	0x12, 0x1c,	0x0d, 0x0b, 0x11, 0x23,0x05 , 0x24,
//  col10
	0x12, 0x2a, 0x0f, 0x52, 0x37, 0x50, 0x50, 0x26,	
//  col 11
	0x18, 0x31, 0x0f, 0x52, 0x36, 0x23, 0x05, 0x26,
//  col12
	0x12, 0x1c, 0x0d, 0x52, 0x11, 0x05, 0x50, 0x24,	
//  col13
	0x42, 0x2a, 0x28, 0x2c, 0x20, 0x4f, 0x4f, 0x43,	
//  col14
	0x21, 0x15, 0x09, 0x2c, 0x2c, 0x51, 0x51, 0x4f,	
//  col15
	0x24, 0x31, 0x1c, 0x0d, 0x11, 0x05, 0x0b, 0x3e,	
//  col16
	0x13, 0x2a, 0x28, 0x52, 0x33, 0x2d, 0x37, 0x27,	
//  col17
	0x13, 0x38, 0x28, 0x28, 0x33, 0x2d, 0x37, 0x27,					
};

#ifdef USE_FOR_CONNECT_RF
const u_int32  rfRegister[] =
{
	
	
	0x00000031,
	0x003f0001,
	0x00000490,
	0x00011090,
	0x000210b1,
	0x000310f1,
	0x000450f0,
	0x000557f0,
	0x00065FF7,
	0x00077FF7,
	0x004D0BB8,
	0x004E0BB8,
	0x004F7F7F,
	0x00402000,
	0x00459800,
	0x00490028,
	0x0047D0B2,
	0x00500812,
	0x003f0000,
	0x0001002F,
	0x00067380,
	0x00084087,
	0x000930fe,
	0x00120005,
	0x00155BF8,
	0x00168320,
	0x00173136,
	0x0018BE10,
	0x001A0604,
	0x001B0022,
	0x001C5007,
	0x000B1070,
	0x000CFFF8,
	0x000E0122,
	0x000D8080,
	0x000F0300,
	0x001D0995,
	0x001E34B0,
	0x0030012B,
	0x003D0020,
	0x0041000B,
	0x004225BD,
	0x0043BFC6,
	0x0044040F,
	0x004B2029,
	0x004908E4,
	0x00694075,
	0x006B10C0,
	0x00462064,
	0x00400000,
};
#else
const u_int32  rfRegister[] =
{
	0x00000031,
		
	
	0x003f0001,
	0x00000490,
	0x00011090,
	0x000210b1,
	0x000310f1,
	0x000450f0,
	0x000557f0,
	0x00065FF7,
	0x00077FF7,
	0x004D0BB8,
	0x004E0BB8,
	0x004F7F7F,
	0x00402000,
	0x00459800,
	0x00490028,
	0x0047D0B2,
	0x00500812,
	0x003f0000,
	0x0001002F,
	0x00067180,
	0x00084087,
	0x000930fe,
	0x00120005,
	0x00150E20,
	0x00168320,
	0x00173136,
	0x0018BE10,
	0x001B0022,
	0x001C5787,	// 0x001Cd71b
	0x000B1070,
	0x000CFFF8,
	0x000E0122,
	0x000D8080,
	0x000F0300,
	0x001A07FC,
	0x001D0B13,
	0x001E34B0,
	0x0030012B,
	0x003D0020,
	0x0041000B,
	0x004225BD,
	0x0043BFC6,
	0x0044040F,
	0x004B2029,
	0x004908E4,
	0x00694075,
	0x006B10C0,
	0x00462064,
	0x00400000,


};
#endif

u_int8 offCount;

#ifdef  TEST_FLASH
extern UINT32 get_flash_status(UINT32 flash_addr);
extern void wait_flash_busy(void);
extern void start_flash_operation(UINT8 cmd, UINT32 addr, UINT8 opmode, UINT16 blocksize);
extern BOOL push_fifo_data(UINT8 data_array[], UINT32 data_cnt, BOOL quard_flag, BOOL clr_flag);
	
extern MEMD_SPIFLSH_RDID_T g_spiflash_ID;
extern UINT8 g_dif_opcode_high_p_mode;

UINT32 p_get_flash_ID(UINT32 flash_addr)
{
    UINT32 data_tmp_32;
    UINT32 addr_tmp;
    UINT8 opmode;
    BOOL quard_flag;
    UINT8 data_array[2];
    UINT8 data_size;

    addr_tmp = SPI_CONFIG;
    data_tmp_32 = MREAD_32(addr_tmp);
    if(FLASH_TYPE_ID==0)
    {
        opmode = 0;
        data_array[1] = 0;
        data_array[0] = 0x0;
        data_size = 0;
    }
    else if(FLASH_TYPE_ID>=TOTAL_FLASH_ID)
    {
        opmode = 3;
        data_array[1] = 0;
        data_array[0] = 0x0;		
        data_size = 2;
    }
    else
    {
        opmode = 3;
        data_array[1] = 0x0;
        data_array[0] = 0;		
        data_size = 1;
    }

    if(data_tmp_32&0x10000)
        quard_flag = TRUE;
    else
        quard_flag = FALSE;
    wait_flash_busy();
    addr_tmp = SPI_FIFO_CTRL;
    data_tmp_32 = 0x3;		
    MWRITE_32(addr_tmp,data_tmp_32);

    wait_flash_busy();

 //   start_flash_operation(OPCODE_WRITE_ENABLE, flash_addr, opmode, 0);
    
//    push_fifo_data(data_array,data_size,quard_flag,TRUE);

    start_flash_operation(OPCODE_RDID, flash_addr, opmode, 3);

    wait_flash_busy();

    data_tmp_32 = MREAD_32(SPI_STATUS);
    while (data_tmp_32 & 0x8)
        data_tmp_32 = MREAD_32(SPI_STATUS);

   wait_flash_busy();


 //   addr_tmp = SPI_READ_BACK;

    
    g_spiflash_ID.manufacturerID = (UINT8)(MREAD_32(SPI_READ_BACK) & 0xff);
    g_spiflash_ID.device_memory_type_ID = (UINT8)(MREAD_32(SPI_READ_BACK) & 0xff);
    g_spiflash_ID.device_capacity_type_ID = (UINT8)(MREAD_32(SPI_READ_BACK) & 0xff);
    
    return data_tmp_32;
}

void p_write_flash_status(UINT32 flash_addr, UINT8 status_val)
{
    UINT32 data_tmp_32;
    UINT32 addr_tmp;
    UINT8 opmode;
    BOOL quard_flag;
    UINT8 data_array[2];
    UINT8 data_size;

    addr_tmp = SPI_CONFIG;
    data_tmp_32 = MREAD_32(addr_tmp);
    if(FLASH_TYPE_ID==0)
    {
	   if((g_spiflash_ID.manufacturerID == MEMD_FLASH_MXIC)||(g_spiflash_ID.manufacturerID ==MEMD_FLASH_ESMT))
    	{
    		opmode = 0;
        	data_array[0] = status_val;
        	data_array[1] = 0x0;
        	data_size = 1;
    	}
		else
		{
        	opmode = 0;
        	data_array[0] = 0x0;
        	data_array[1] = status_val;
        	data_size = 2;
		}
    }
    else if(FLASH_TYPE_ID>=TOTAL_FLASH_ID)
    {
        opmode = 3;
        data_array[1] = status_val;
        data_array[0] = 0x0;		
        data_size = 2;
    }
    else
    {
        opmode = 3;
        data_array[1] = 0x0;
        data_array[0] = status_val;		
        data_size = 1;
    }

    if(data_tmp_32&0x10000)
        quard_flag = TRUE;
    else
        quard_flag = FALSE;
    wait_flash_busy();
    addr_tmp = SPI_FIFO_CTRL;
    data_tmp_32 = 0x3;		
    MWRITE_32(addr_tmp,data_tmp_32);

    wait_flash_busy();

    start_flash_operation(OPCODE_WRITE_ENABLE, flash_addr, opmode, 0);
    push_fifo_data(data_array,data_size,quard_flag,TRUE);
    start_flash_operation(OPCODE_WRITE_STATUS, flash_addr, opmode, 0);

/*
    start_flash_operation(OPCODE_WRITE_ENABLE, flash_addr, 3, 0);
    push_fifo_data(data_array,data_size,quard_flag,TRUE);
    start_flash_operation(OPCODE_WRITE_STATUS, flash_addr, 3, 0);
*/    

    data_tmp_32 = get_flash_status(flash_addr);
    while (data_tmp_32&0x1)
        data_tmp_32 = get_flash_status(flash_addr);

    return ;
}


BOOL p_spi_flash_quard_ctrl(BOOL quard_en_flag, UINT8 dual_mode)
{
    UINT32 data_tmp_32;
    UINT32 addr_tmp;
    UINT8 qmode_cmd;

    UINT8 opmode;
    BOOL quard_flag;
    UINT8 status_val;
    UINT32 flash_addr;

    addr_tmp = SPI_CONFIG;
    data_tmp_32 = MREAD_32(addr_tmp);
    if(data_tmp_32&0x10000)
        quard_flag = TRUE;
    else
        quard_flag = FALSE;

    if(FLASH_TYPE_ID)
        opmode = 3;
    else
        opmode = 0;

    if(quard_en_flag&(FLASH_TYPE_ID ==1))
        status_val = 0x40;
    else 
	if(FLASH_TYPE_ID ==2)
        	status_val = 0x0;
    else 
	if(quard_en_flag)
    {
			if((g_spiflash_ID.manufacturerID == MEMD_FLASH_MXIC)||(g_spiflash_ID.manufacturerID ==MEMD_FLASH_ESMT))
				status_val = 0x40;
			else  
				status_val = 0x02;
    }
    else
        status_val = 0x0;

    if(dual_mode == 1)
        flash_addr = 0x400000;
    else if(dual_mode == 3)
        flash_addr = 0x800000;
    else
        flash_addr = 0x0;	
	if(g_spiflash_ID.manufacturerID == MEMD_FLASH_EON)
	{
	
	}
	else
	{
        p_write_flash_status(0,status_val);
        if(dual_mode)
            p_write_flash_status(flash_addr,status_val);
    }

    if(FLASH_TYPE_ID == 0x2)
    {
        if(quard_en_flag)
            qmode_cmd = 0x38;
        else
            qmode_cmd = 0xff;

        start_flash_operation(OPCODE_WRITE_ENABLE, flash_addr, opmode, 0);
        start_flash_operation(qmode_cmd,flash_addr,opmode,0);

        if(dual_mode)
        {
            start_flash_operation(OPCODE_WRITE_ENABLE, flash_addr, opmode, 0);
            start_flash_operation(qmode_cmd,flash_addr,opmode,0);
        }
    }	
    start_flash_operation(g_dif_opcode_high_p_mode, flash_addr, opmode, 0);

    addr_tmp =SPI_CONFIG;
    data_tmp_32 = MREAD_32(addr_tmp);			
    if(quard_en_flag)
        data_tmp_32 = data_tmp_32|0x1;
    else
        data_tmp_32 = data_tmp_32&0xfffffffe;

    if((FLASH_TYPE_ID == 2)&quard_en_flag)
        data_tmp_32 = data_tmp_32 | 0x10000;
    else
        data_tmp_32 = data_tmp_32&0xfffeffff;
    wait_flash_busy();
    MWRITE_32(addr_tmp,data_tmp_32);

    return TRUE;
}

void p_spi_flash_ini(BOOL quard_flag, UINT8 clk_offset_val, UINT8 clkdiv_val, UINT8 dual_mode)
{
    UINT32 data_tmp_32;
    UINT32 addr_tmp;
    wait_flash_busy();
    addr_tmp = SPI_CS_SIZE;
    data_tmp_32 = dual_mode&0x3;
    MWRITE_32(addr_tmp, data_tmp_32);
    wait_flash_busy();
    addr_tmp = SPI_CONFIG;
    data_tmp_32 = ((clk_offset_val<<4)|(clkdiv_val<<8))&0xff70;
    MWRITE_32(addr_tmp,data_tmp_32);

    p_get_flash_ID(0);   
    p_spi_flash_quard_ctrl(quard_flag,dual_mode);
    wait_flash_busy();

#ifdef SPI_FLASH_CONTINUOUS_READ
    addr_tmp = SPI_BLOCK_SIZE;
    data_tmp_32 = (0xaf)&0xff;
    MWRITE_32(addr_tmp,data_tmp_32);
#endif

    
}	


void p_SPI_Flash_Open()
{
    UINT8 clk_div;
    if(FLASH_TYPE_ID == 0x1) clk_div = 0x8;
    else clk_div = 0x2;
    clk_div = 0x8;
    
    p_spi_flash_ini(FALSE,0x2,clk_div,0x0);
    return;
}

u_int8 spiflashout[12];

void HID_Flash_SpecFun(u_int8 *data,u_int8 length)
{
	UINT32 s;
	
	u_int8 spiflashin[12] = 
	{
	0xaa,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xbb
	};
	
	switch(data[0]){
	
	case 0x00:
		HW_Flash_Erase(0,0);
		//spi_flash_chip_erase(0);
		//spi_flash_block_erase(0);
		//spi_flash_sector_erase(0);
		break;
	case 0x01:
		//memd_FlashWrite((UINT8*)0x03,7, &s,spiflashin);
		HW_Flash_Sequen_write(data[1],spiflashin,data[2]);
		//HW_Flash_Sequen_write(0x00,spiflashin,data[1]);
		break;
	case 0x02:
		//memd_FlashRead((UINT8*)0x07,4,&s,spiflashout);
		HW_Flash_Sequen_read(data[1],spiflashout,data[2]);
		HID_Send_UART(spiflashout,data[2]);
		break;
	case 0x03:
		p_SPI_Flash_Open();
		spiflashout[0] = 0xcc;
		spiflashout[1] = g_spiflash_ID.manufacturerID;
		HID_Send_UART(spiflashout,2);
		break;
		
	default:
		break;

	}
}
#endif


void p_hid_shutdown_device(void)
{
	u_int8 arr[4];
	arr[0]=arr[1]=arr[2]=0x44;
	HID_Send_UART(arr,3);

	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+0x520,0xd); // Enable_ADC_BIAS
	
	SYSpwr_Set_Register_Bit(RDA_APB_SCU_CLKGATE_REG,RDA_SCU_PCLKPMUCLKEN_BIT, 1);
	HWdelay_Wait_For_us(5);
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+0x408,RDA_READ_REG_BYTE(RDA_APB_PMU_BASE+0x408)|0x10);//lpo on
    HWdelay_Wait_For_us(5);
    RDA_WRITE_REG(RDA_APB_PMU_BASE+0x400,1);
}


u_int8 realVol;
u_int8 p_hid_get_battery()
{
	u_int32 value;
	u_int8  ret=0xff;
	
	
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+0x50c,0x80);//channel 
	

#if 0
	if(2!=((*(volatile u_int8*)(RDA_APB_PMU_BASE+0x520))&2))
	{
		//RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+0x10b,RDA_READ_REG_BYTE(RDA_APB_PMU_BASE+0x10b)|0x10);//open adc clock,ygh
		//RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+0x109,RDA_READ_REG_BYTE(RDA_APB_PMU_BASE+0x109)|0x80);//bypass adc filter,ygh
		(*(volatile u_int8*)(RDA_APB_PMU_BASE+0x520))|=2;
	}
#else
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x148<<2),0xf);
#endif

	HWdelay_Wait_For_us(200);

	value=RDA_READ_REG(RDA_APB_PMU_BASE+(0x150<<2));

	
		
	if(value&0x8000){
		
		
		realVol=(u_int8)(value>>2&0xff);

				
		if(realVol<gEfuse[0])
		{
			
			
			ret= LOWEST_POWER;
		}

		else
			ret= NORMAL_POWER;

		// HSMain_Disable_ADC_BIAS
		RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x148<<2),4);
	}


	return ret;
}

void p_hid_Power_Detect(void *dummy)
{
	u_int8 level;
	
	level=p_hid_get_battery();

	if(level==0xff)
		return;
		
	if(level==LOWEST_POWER)
	{
		offCount++;
			
	}
	else{
		offCount=0;
		
	}
		
	if(offCount>=3){		
		rdabt_cancel_timer(gPowerT);
		gPowerT=0;
		
		p_hid_shutdown_device();
		
		
	}
		
}

void p_hid_Sleep_reg(void)
{
	//RDA_WRITE_REG(0x4024001c, 0x0e);  --Notice: There is NOT 0x1c in the 71.

	//RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x128<<2),0x04);  // Can't off VIO in sleep, bit 6

	
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x128<<2),0x40);
	// HSMain_Enable_ADC_BIAS, for Power_Detect
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x148<<2),0x04);	
}


void p_hid_Wake_reg(void)
{
	
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x128<<2),0x49);
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x148<<2),0x0d);
		
}


void p_hid_InitSleepMode(void *dummy)
{
	g_sys_config.standby_sleep_period = 0x50; //default: 0x50
	p_hid_Sleep_reg();
    
    SYSpwr_Set_LowFrequencyOscillatorAvailable_Value(SYS_LF_OSCILLATOR_PRESENT);
    SYSpwr_Set_Register_Bit(RDA_APB_SCU_DEEPSLEEP_REG, RDA_SCU_DEEPSLEEPENABLE_BIT, 1);
}


void p_hid_RF_CALIB()
{
	_HWradio_ProgNow((0x30 <<16) | 0x016b);
	_HWradio_ProgNow((0x3c <<16) | 0x06fe);
	_HWradio_ProgNow((0x30 <<16) | 0x0169);
	HWdelay_Wait_For_us(10);
	_HWradio_ProgNow((0x30 <<16) | 0x016b);
	HWdelay_Wait_For_us(10);
	_HWradio_ProgNow((0x30 <<16) | 0x012B);
}


void p_hid_init(void)
{
	u_int32 value;
	u_int8  i,tmp;
	u_int8 arr[4];
	

	u_int32 *p_attr = (u_int32*)attribute_pnp;
	
	p_attr[31] = 0x000005ac;  //Vendor ID: a 0x05ac RDA:0x61 
	p_attr[35] = 0x0000022c;  //product ID:a 0x022c


	r71TestFlag = (u_int8)(hid_func_db[15] & 0xff);

#if 0
	arr[0]=arr[1]=0x11;
	arr[2]=r71TestFlag;
	HID_Send_UART(arr,3);
#endif

	if(r71TestFlag & HID_DEBUG_SLEEP){
		r71TestFlag |= HID_DEBUG_SNIFF_3;
		g_LM_config_info.default_link_policy_mode = LINK_POLICY_SNIFF_ENABLED|LINK_POLICY_SWITCH_ENABLED;
	}
	else{
		g_LM_config_info.default_link_policy_mode = LINK_POLICY_SWITCH_ENABLED;
		g_sys_config.feature_set[0] = 0x3f;	// Disable Sniff mode
	}

	// for BQB's DUT test
	if(r71TestFlag & HID_DEBUG_DUT_MODE)
		BTtst_dut_mode = 1;

	hFifoIndex = 0;   // clear the index of HW FIFO 

	/* Set the new CoD */
	//g_sys_config.device_class = 0x02010c;  // laptop
	//FHS_Set_Device_Class(&LC_local_device_fhs, g_sys_config.device_class);

	/* Set the new BaudRate */
	//HCIT_Chimera_16550_Set_BaudRate(9600);

		//SYSconfig_Enable_Feature(PRH_BS_CFG_SYS_LMP_SECURE_SIMPLE_PAIRING_HOST_FEATURE);

	
	/* disable ACL edr  */
	g_sys_config.feature_set[3] = 0xc8;
	/* disable ESCO edr  */
	g_sys_config.feature_set[5] &= 0x18;
	
	

#ifdef TEST_PINCODE
	// Pin Code
	g_sys_config.feature_set[6] = 0x51;   
	g_sys_config.feature_set[7] = 0x00; 
	usePinCode = 1;
#else
	// SSP
	g_sys_config.feature_set[6] = 0x59;    //0xf7 specified for ssp  (close SSP)
    g_sys_config.feature_set[7] = 0x87;   // 0x7b specified for ipad
#endif

	// for Direct HID TX
	HID_Init_RawData();
	// SDP
	HID_Init_KB_SDP();
	
		// Remove the other SDPs
	   rdabt_sdp_replace_service(0x10000, NULL); // remove hfp sdp record
#if 1
	    rdabt_sdp_replace_service(0x10001, NULL); // remove hs sdp record
	    rdabt_sdp_replace_service(0x10007, NULL); // remove spp sdp record
	     rdabt_sdp_replace_service(0x10003, NULL); // remove avrcp sdp record
		rdabt_sdp_replace_service(0x10002, NULL); // remove a2dp sdp record
#endif

	gLinkIndex = LMkeydb_EE_Load_Link();	
	// for test 
	//gKeyFlag = 0;

	ghid.pinCodeStatus = HID_PINCODE_IDLE;

	
	
	// mask int 
	_HID_INT_Disable();

	RDA_WRITE_REG(0x40160004,0x19);    // I2c slave


	// low power
	if(r71TestFlag & HID_DEBUG_SLEEP){
		//RDA_WRITE_REG_BYTE(0X40250000+0x1a7,1);
		// Notice:  <= 10ms, Not Sleep,is relevant to the "Sniff min_interval" !
		g_sys_config.min_sleep_interval = 0x10; 
		_r2p_min_search_window = 1;
		g_min_wakeup_interval       = 0x1;
		// g_min_wakeup_interval    = 0x0;  // patch for 4th metal 

	}
	
	// Begin of Register Setting
	HID_WRITE_REG_UINT8(0x40,0x00);
	
	 
	// Set 5408 interface by SPI 0x13*4+0x200 
	//HW_SPI_Write_Data(0x24c,0x0c24);  // set p0_5, p0_6 pull up
	

	HID_WRITE_REG_UINT32(0x04,~0x0);		//enable row

	HID_WRITE_REG_UINT32(0x14,0x70000000);  // pull up
	HID_WRITE_REG_UINT32(0x18,0xff);   // pull down 
#if(FPGA_MODE_ENABLE == 1)
	HID_WRITE_REG_UINT32(0x10,0x30ffffff);  // oenb
	//Unit is 1ms(FPGA) / 125us(ASIC)
	//HID_WRITE_REG_UINT8(0x6c,0x0a);	// 0x1-7f,bit[6:0] keyboard debounce ,Default is 0x3c(ms)
#else
	HID_WRITE_REG_UINT32(0x10,0x000000ff);  // oenb	0x300000ff
	//HID_WRITE_REG_UINT8(0x6c,0x50);	// 10ms
#endif
	// Unit is 125us/clock 128k,(40240008[21:16] prolong the clock)
	HID_WRITE_REG_UINT8(0x6c,0x3f);	// 0x50:10ms ,0x3f:7.875ms(max),default:3ms
	
	
	HID_WRITE_REG_UINT8(0x74,0x9f);		//col row num
    HID_WRITE_REG_UINT8(0x78,0x33);		 //idle time
	

	



	//HID_WRITE_REG_UINT32(0x10,0xff);

	//HID_Set_LED(hid_led_num[0],LED_ALWAYS_LIGHT,0x0);
	//hidTimerIdx = LMtmr_Set_Timer(600*hid_config_eeprom.scanDuration*160,_HID_Close_Scan,NULL,1);
	//hidTimerIdx = rdabt_timer_create(600*hid_config_eeprom.scanDuration, _HID_Close_Scan, NULL, RDABT_TIMER_ONESHOT); //10:1 sec
	
	
	
	 // reset hid soft reset bit0
   tmp = HID_READ_REG_UINT8(0x68);
   tmp &= 0xfe;
   HID_WRITE_REG_UINT8(0x68,tmp);
   tmp |= 0x01;
   HID_WRITE_REG_UINT8(0x68,tmp);

  
	_HID_INT_Enable();    // enable  int
	
#if(FPGA_MODE_ENABLE == 1)
	HID_WRITE_REG_UINT8(0x40,0x05);	 // 160 keys scan enable
#else
	HID_WRITE_REG_UINT8(0x40,0x01);	 // 160 keys scan enable
#endif

	// End of Register Setting


	HID_WRITE_REG_UINT8(0xe8,0x0f);  // Pwm_led_en

	// It's no use !!
	// HSBattery_Initialise();
	
#if 0
	
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+0x10c,0x30);  // disable HW control LED
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+0x10b,RDA_READ_REG_BYTE(RDA_APB_PMU_BASE+0x10b)&0xfe);  // Disable Charger INT
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+0x1a7,1); // 26M stablize time : 1ms
#endif

#if 0
	if(gLinkIndex != 0xff){		
		L2_GetInfo(ghid.address,0x01,p_hid_reconnect);
		
	}
#endif	
	// for test
	//HSMain_InitSleepMode(NULL);
	//rdabt_timer_create(hid_config_eeprom.sleepTime*10, HSMain_InitSleepMode, NULL, pTIMER_ONESHOT);  // n(s)

	

	// set led  bit17: clk_sel = fast  impact on the LED
	HID_WRITE_REG_UINT32(0x30,0x800000);  	
	// slow flash
	HID_WRITE_REG_UINT32(0xf0,hid_config_eeprom.scanInit);
	HID_WRITE_REG_UINT32(0xf8,hid_config_eeprom.scanToggle);
	//quick flash
	HID_WRITE_REG_UINT32(0xf4,hid_config_eeprom.lowPowerInit);
	HID_WRITE_REG_UINT32(0xfc,hid_config_eeprom.lowPowerToggle);

	
	

	// MUST Enter sleep mode after a few minutes for Downloading the FLASH on the 71E
	if(r71TestFlag & HID_DEBUG_SLEEP){
		
		rdabt_timer_create(hid_config_eeprom.sleepTime*10, p_hid_InitSleepMode, NULL, pTIMER_ONESHOT);  // n(s)
	}


	//MGR_SetSecurityMode(MGR_NOSECURITY); // Notice: for XP without authentication
	if(r71TestFlag & HID_DEBUG_SCAN)
		LMscan_Write_Scan_Enable(BOTH_SCANS_ENABLED);  // BOTH_SCANS_ENABLED
	
	//HID_FLASH_LED(0,0);
	HID_Set_LED(1,HID_LED_OFF,0xff);
	//HID_FLASH_LED(3,1);
	HID_Set_LED(3,HID_LED_ON,0xff);

	// patch
	//codec
	RDA_WRITE_REG(0x40260014,0x01fd);	// turn off codec

	// pmu
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x102<<2),0x12);	// Don't use LPO in sleep
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x142<<2),0x83);

	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x104<<2),0x0d);
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x128<<2),0x49); 	// turn on VIO
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x112<<2),0x36);
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x121<<2),0x48);	// turn off AVDD
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x123<<2),0x10);
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x124<<2),0x48);
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x125<<2),0xfc);
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x126<<2),0x16);
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x129<<2),0x13);
	
	
	
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x12a<<2),0x85);
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x12b<<2),0xa0);
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x138<<2),0x06);
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x148<<2),0x04);
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x14d<<2),0x00); // 71E: 00, Disable Codec
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x12d<<2),0x9f);
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x12e<<2),0x2c);
	// HSMain_Enable_ADC_BIAS, for Power_Detect
	RDA_WRITE_REG_BYTE(RDA_APB_PMU_BASE+(0x148<<2),0xd); 

	// RF
	SYSHal_Config_Apply(0x26, sizeof(rfRegister), (u_int8 *)rfRegister); // SYS_CONFIG_ID_RF_REGISTER
	//SYSHal_Config_Apply(0x23, 0, NULL);   // SYS_CONFIG_ID_RF_CALIB
	p_hid_RF_CALIB();

	

	HW_Random_Read(gEfuse); // impact on 0x20

	// Set it into the digital mode,Bit[28:21]:0: Analog 1:digital
#if 0
	value = HID_READ_REG_UINT32(0x20);
	value |= 0x1f<<21;
	HID_WRITE_REG_UINT32(0x20,value);
#else
	HID_WRITE_REG_UINT32(0x20,0x1fe00000);
#endif


	
}

extern u_int8 gKeyFlag;
extern u_int8 gha_fifo[NUM_OF_HARD_FIFO];
extern u_int8 ghardLen;
extern u_int16     gHidHandle;
extern u_int8 	 gfi;
extern u_int8   array_index;
extern u_int8	 *fifoPtr[NUM_OF_HID_FIFO];
extern u_int8   gHidFifoUsed[NUM_OF_HID_FIFO];

extern u_int8 isGhost(u_int8 *ptr,u_int8 len);

void p_HID_Reconnect(void)
{

	
	if(ghid.state == HidIdle){
			
		if(gLinkIndex != 0xff){
			if(gKeyFlag == 0)
				MGR_SetSecurityMode(1); // 1: MGR_NOSECURITY
			else
				MGR_SetSecurityMode(2);	// 2: MGR_SERVICELEVEL
			
			
			HID_Connect(ghid.address);
		}
	}
}


void p_hid_isr(void)
{
	u_int8   num,status,length,i,m;
	u_int8   column_index,row_index,matrix_index;
	u_int8   arr[4];
	
	
	status = HID_READ_REG_UINT8(KEYBOARD_STATUS_OFFSET);	// // and clear the keyboard int


	
	//arr[0]=arr[1]=arr[2]=0x33;
	//HID_Send_UART(arr,3);


	if(r71TestFlag & HID_DEBUG_SLEEP)
		p_hid_Wake_reg();
	
	

	length = status >> 4;

	memset(gha_fifo,0,8);

	
	if(r71TestFlag & HID_DEBUG_KEY_RECONN){
		p_HID_Reconnect();
		
		//if((ghid.state == HidIdle)&&(gLinkIndex != 0xff))
		//	HID_Connect(ghid.address);
	}
	

	if(gHidHandle != 0)
			rdabt_update_sniff_timer(gHidHandle);

	if(status & 0x04){		// press

		if(length == 0)
			goto NOR_EXIT;


		ghardLen=0;
		//key_test_value = 1;
		// get hardware row and column
		for(i=0;i<length;i++)
		{		
			m = HID_READ_REG_UINT8(KEYBOARD_FIFO_OFFSET+hFifoIndex*4); // sure that it's on the top
			hFifoIndex++;
			if(hFifoIndex == NUM_OF_HARD_FIFO)
				hFifoIndex = 0;
			 // calculate the index		
			 gha_fifo[ghardLen] = m;
			 ghardLen++;
			
			 
		}

		if(status & KEYBOARD_STATUS_GHOST)
			goto NOR_EXIT;
	
		// check if the ghost to fix the HW bug
		if(isGhost(gha_fifo,length))
			goto NOR_EXIT;

	
		//HID_Send_UART(gha_fifo,ghardLen);

		if(ghid.state != HidConnected)
			goto NOR_EXIT;

		array_index = 8;  // location of 1st key's ScanCode

		memset(&fifoPtr[0][6],0,8); // zero the scancode domain
				
		for(i=0;i<ghardLen;i++)
		{
			row_index = gha_fifo[i] & 0x07;
			column_index = (gha_fifo[i]>>3) & 0x1f;
			matrix_index = (column_index * 8) + row_index;
			

			fifoPtr[0][array_index++] = MY_KB_scan_table[matrix_index];  //keyboard_scan_table[matrix_index];
			
		}
		gfi = 0;		// ensure to take the press_FIFO firstly
		gHidFifoUsed[0] = 1;
	}
	else{			// release	
		//HID_Send_UART(gha_fifo,ghardLen);

		if(ghid.state != HidConnected)
			goto NOR_EXIT;

		gHidFifoUsed[1] = 1;
		
	}

	

	
NOR_EXIT:
		
		// confirm the interrupt to be cleared.  --cliff
		while(1){
			num = HID_READ_REG_UINT8(KEYBOARD_STATUS_OFFSET);
			if(!(num & 0x01))
				break;
			
	
		}	

		
		if(r71TestFlag & HID_DEBUG_SLEEP)
				p_hid_Sleep_reg();


}



u_int8 p_hid_Schedule(void)
{
	

	
}





void p_hid_Run_Spec_Fun(u_int8 *data,u_int8 length)
{
	u_int8 val[8];

#ifdef  TEST_FLASH
		HID_Flash_SpecFun(data,length);
		return;
#endif

	switch(data[0])
	{
	case 0xaa:
		HW_Random_Read(val);
		HID_Send_UART(val,6);
		break;
	case 0xbb:
		if(gPowerT==0)
			gPowerT = rdabt_timer_create(DTECT_POWER_INTERVAL, p_hid_Power_Detect, NULL, pTIMER_PERIODIC);
		break;
	default:
		break;
	
	}
	
}



